<?php

namespace Wechat;

use app\admin\model\Config;
use EasyWeChat\OfficialAccount\Application;
use Exception;
use util\Logger;

class CommerceApp
{
	private static      $instance;
	private Application $app;
	private array       $config;

	/**
	 * @throws Exception
	 */
	private function __construct()
	{
		try {
			$db_config    = Config::where('group', 'wx_team')->column('name, value');
			$this->config = $db_config;
			$config       = [
				'app_id'                  => $db_config['wx_team_appid'],
				'secret'                  => $db_config['wx_team_secret'],
				'token'                   => $db_config['wx_team_token'],
				'aes_key'                 => $db_config['wx_team_msg_key'],
				'use_stable_access_token' => true,
				'http'                    => [
					'throw'   => true, // 状态码非 200、300 时是否抛出异常，默认为开启
					'timeout' => 5.0,
					'retry'   => true, // 使用默认重试配置
				],
			];
			$this->app    = new Application($config);
		} catch (Exception $e) {
			$log = [
				'file' => $e->getFile(),
				'line' => $e->getLine(),
				'msg'  => $e->getMessage(),
			];
			Logger::error('获取配置失败', $log);
			throw new Exception('获取配置失败');
		}
	}

	public static function getInstance(): self
	{
		if (!self::$instance instanceof self) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	public function getApp()
	{
		return $this->app;
	}

	/**
	 * 获取微信服务
	 *
	 * @throws \Throwable
	 */
	public function getServer()
	{
		try {
			return $this->app->getServer();
		} catch (\Exception $e) {
			Logger::error('获取微信服务失败: ' . $e->getMessage());
			throw new Exception('获取微信服务失败');
		}
	}

	/**
	 * 解密获取回调消息
	 *
	 * @param array $data
	 */
	public function decryptNotifyMsg(array $data)
	{
		$params = [$this->config['wx_team_token'], $data['timestamp'], $data['nonce'], $data['Encrypt']];
		sort($params, SORT_STRING);
		$rawString          = implode('', $params);
		$generatedSignature = sha1($rawString);
		if ($generatedSignature != $data['msg_signature']) {
			Logger::error('签名验证失败');
//            throw new \Exception('签名验证失败');
		}
		// 1. 生成 AESKey（严格验证）
		$aesKey = base64_decode($this->app->getConfig()->get('aes_key') . "=");
		// 2. Base64 解码加密数据
		$encryptedData = base64_decode($data['Encrypt']);
		// 3. 生成 IV（取 AESKey 前16字节）
		$iv = substr($aesKey, 0, 16);
		// 4. AES-256-CBC 解密（显式处理 PKCS#7 填充）
		$decrypted = openssl_decrypt(
			$encryptedData,
			'AES-256-CBC',
			$aesKey,
			OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, // 关键修改：禁用自动填充,
			$iv
		);
		if ($decrypted === false) {
			throw new \Exception("解密失败: " . openssl_error_string());
		}
		// 5. 手动去除 PKCS#7 填充（关键步骤）
		$pad       = ord(substr($decrypted, -1));// 获取最后一个字节的填充值
		$decrypted = substr($decrypted, 0, -$pad);
		// 6. 解析消息结构（严格按字节处理）
		$msgLen        = unpack('N', substr($decrypted, 16, 4))[1]; // 4B 网络字节序
		$msg           = substr($decrypted, 20, $msgLen); // msg 明文
		$receivedAppId = substr($decrypted, 20 + $msgLen); // 剩余部分为 AppId
//        // 7. 验证 AppId
//        if ($receivedAppId !== $this->config['wx_team_appid']) {
//            throw new \Exception("AppID验证失败");
//        }
		return $msg;
	}

	/**
	 * 获取机构选品广场商品列表
	 *
	 * @param int    $plan_type
	 * @param string $next_key
	 * @return array
	 */
	public function squareGoodsLists(int $plan_type, int $spu_source = 1, string $next_key = '')
	{
		//plan_type: 商品的计划类型 1：定向计划 2：公开计划 3: 机构定向计划 4: 机构普通计划
		$params = [
			'plan_type'  => $plan_type,
			'spu_source' => $spu_source,
			'page_size'  => 20,
			'next_key'   => $next_key,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/league/headsupplier/selectionproducts/list/get", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			var_dump($res);
			exit;
			$product_list = $res['product_list'];
			$next_key     = $res['next_key'] ?? '';
			return [$product_list, $next_key];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取推客推广商品列表
	 *
	 * @param int    $plan_type
	 * @param string $next_key
	 * @return array
	 */
	public function goodsLists(int $plan_type, string $next_key = '')
	{
		//plan_type: 商品的计划类型 1：定向计划 2：公开计划 3: 机构定向计划 4: 机构普通计划
		$params = [
			'plan_type' => $plan_type,
			'page_size' => 20,
			'next_key'  => $next_key,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_promote_product_list", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			$product_list = $res['product_list'];
			$next_key     = $res['next_key'] ?? '';
			return [$product_list, $next_key];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取推客推广商品详情
	 */
	public function goodsDetail(string $shop_appid, string $product_id, int $plan_type, string $head_supplier_appid = '')
	{
		$params = [
			'shop_appid' => $shop_appid,
			'product_id' => $product_id,
			'plan_type'  => $plan_type,
		];
		if ($plan_type == 3 || $plan_type == 4) {
			if (empty($head_supplier_appid)) {
				throw new Exception('商品所属供货机构appid不能为空');
			}
			$params['head_supplier_appid'] = $head_supplier_appid;
		}
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_promote_product_detail", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['product'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取商品基础详情
	 */
	public function goodsBaseDetail(string $shop_appid, string $product_id)
	{
		$params = [
			'shop_appid' => $shop_appid,
			'product_id' => $product_id,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/league/headsupplier/productdetail/get", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['item'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取某个推客某个商品的内嵌商品卡片product_promotion_link
	 */
	public function getProductPromotionLink(string $product_id, string $shop_appid, string $head_supplier_appid, string $sharer_openid)
	{
		$params = [
			'sharer_openid'       => $sharer_openid,
			'product_id'          => intval($product_id),
			'shop_appid'          => $shop_appid,
			'head_supplier_appid' => $head_supplier_appid,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_promoter_single_product_promotion_info", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['product_promotion_link'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取推客对某个商品的推广短链
	 */
	public function getProductPromotionQrcodeInfo(string $product_id, string $shop_appid, string $head_supplier_appid, string $sharer_appid)
	{
		$params = [
			'sharer_appid'        => $sharer_appid,
			'product_id'          => intval($product_id),
			'shop_appid'          => $shop_appid,
			'head_supplier_appid' => $head_supplier_appid,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_product_promotion_qrcode_info", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['qrcode_url'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取推客对某个商品的推广短链
	 */
	public function getProductPromotionLinkInfo(string $product_id, string $shop_appid, string $head_supplier_appid, string $sharer_appid)
	{
		$params = [
			'sharer_appid'        => $sharer_appid,
			'product_id'          => intval($product_id),
			'shop_appid'          => $shop_appid,
			'head_supplier_appid' => $head_supplier_appid,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_product_promotion_link_info", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['short_link'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取机构绑定的推客信息
	 */
	public function bindSharerList(array $params, string $next_key = '')
	{
		$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_bind_sharer_list", $params)->toArray();

		echo "<pre>";
		print_r($res);
		die;


		$params = [
			'page_size' => 20,
			'next_key'  => $next_key,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_bind_sharer_list", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return [$res['sharer_info_list'], $res['next_key']];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取推客的注册状态，以及和机构的绑定状态
	 */
	public function RegisterAndBind(string $sharer_openid = '', string $sharer_appid = '')
	{
		if (empty($sharer_appid) && empty($sharer_openid)) {
			throw new Exception('sharer_appid和sharer_openid不能同时为空');
		}
		$params = [
			'is_simple_register' => true,
		];
		if ($sharer_openid) {
			$params['sharer_openid'] = $sharer_openid;
		}
		if ($sharer_appid) {
			$params['sharer_appid'] = $sharer_appid;
		}
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_promoter_register_and_bind_status", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			$res['appid'] = $this->config['wx_team_appid'];
			return $res;
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取合作的达人平台列表
	 */
	public function getBindTalentList(string $next_key = '', string $talent_appid = '')
	{
		$params = [
			'page_size' => 10,
			'next_key'  => $next_key,
		];
		if ($talent_appid) {
			$params['talent_appid'] = $talent_appid;
		}
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_bind_talent_list", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return [$res['talent_list'], $res['next_key'] ?? '', $res['has_more'] ?? false];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取达人平台的直播列表
	 */
	public function getLiveList(string $talent_appid, string $mini_program_appid, string $sharer_appid = '')
	{
		$params = [
			'talent_appid'       => $talent_appid,
			'mini_program_appid' => $mini_program_appid,
		];
		if ($sharer_appid) {
			$params['sharer_appid'] = $sharer_appid;
		}
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_live_record_list", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['live_record_list'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取达人平台的直播预约列表
	 */
	public function getLiveNoticeList(string $talent_appid, string $mini_program_appid)
	{
		$params = [
			'talent_appid'       => $talent_appid,
			'mini_program_appid' => $mini_program_appid,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_live_notice_record_list", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['live_notice_record_list'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取达人直播商品列表
	 */
	public function getLiveGoodsList(string $talent_appid, string $next_key = '')
	{
		$params = [
			'talent_appid' => $talent_appid,
			'next_key'     => $next_key,
			'page_size'    => 10,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_live_commission_product_list", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return [$res['product_list'], $res['next_key'], $res['has_more']];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 为某个推客生成单个直播的推广二维码
	 */
	public function getLiveQrCode(string $talent_appid, string $sharer_appid, string $export_id)
	{
		$params = [
			'talent_appid' => $talent_appid,
			'sharer_appid' => $sharer_appid,
			'export_id'    => $export_id,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_live_record_qr_code", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['qrcode_url'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 为某个推客生成单个直播预约的推广二维码
	 */
	public function getLiveNoticeQrCode(string $talent_appid, string $sharer_appid, string $export_id)
	{
		$params = [
			'talent_appid' => $talent_appid,
			'sharer_appid' => $sharer_appid,
			'notice_id'    => $export_id,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_live_notice_record_qr_code", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['qrcode_url'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取达人平台推广的短视频列表
	 */
	public function getFeedList(string $next_key = '', string $talent_appid = '', string $finder_exportusername = '')
	{
		$params = [
			'next_key'  => $next_key,
			'page_size' => 10,
		];
		if ($talent_appid) {
			$params['talent_appid'] = $talent_appid;
		}
		if ($finder_exportusername) {
			$params['finder_exportusername'] = $finder_exportusername;
		}
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_feed_list", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return [$res['feed_list'], $res['next_key'], $res['has_more']];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 生成某个达人平台的某些短视频内嵌短视频卡片需要的feedtoken
	 */
	public function getFeedInfo(string $talent_appid, string $mini_program_appid, string $export_id, string $sharer_appid = '')
	{
		$params = [
			'talent_appid'       => $talent_appid,
			'mini_program_appid' => $mini_program_appid,
			'feed_list'          => [
				['export_id' => $export_id],
			],
		];
		if ($sharer_appid) {
			$params['sharer_appid'] = $sharer_appid;
		}
		if ($talent_appid) {
			$params['talent_appid'] = $talent_appid;
		}
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/promoter/get_feed_promotion_info", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['feed_list'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取订单列表
	 */
	public function getOrderList(string $next_key = '', string $sharer_appid = '', int $start_time = 0, int $end_time = 0, string $order_id = '')
	{
		$params = [
			'next_key'  => $next_key,
			'page_size' => 25,
		];
		if ($sharer_appid) {
			$params['sharer_appid'] = $sharer_appid;
		}
		if ($start_time && $end_time) {
			$params['create_time_range'] = [
				'start_time' => $start_time,
				'end_time'   => $end_time,
			];
		}
		if ($order_id) {
			$params['order_id'] = $order_id;
		}
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/league/headsupplier/order/list/get", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return [$res['list'], $res['next_key'] ?? ''];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取订单详情
	 */
	public function getOrderInfo(string $order_id, string $sku_id)
	{
		$params = [
			'order_id' => $order_id,
			'sku_id'   => $sku_id,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/league/headsupplier/order/get", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['commssion_order'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取合作小店列表
	 */
	public function getShopList(string $next_key = '')
	{
		$params = [
			'next_key'  => $next_key,
			'page_size' => 30,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/league/headsupplier/shop/list/get", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return [$res['shop_list'], $res['next_key'] ?? '', $res['has_more'] ?? false];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取合作小店详情
	 */
	public function getShopInfo(string $appid)
	{
		$params = [
			'appid' => $appid,
		];
		try {
			$res = $this->app->getClient()->postJson("/channels/ec/league/headsupplier/shop/get", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['shop_detail'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取资金流水列表
	 *
	 * @return array
	 */
	public function getFlowList(int $page = 1, string $next_key = '', int $start_time = 0, int $end_time = 0)
	{
		$params = [
			'page'       => $page,
			'page_size'  => 10,
			'next_key'   => $next_key,
			'funds_type' => 2,
		];
		if ($start_time && $end_time) {
			$params['start_time'] = $start_time;
			$params['end_time']   = $end_time;
		}
		try {
			$res = $this->app->getClient()->postJson("channels/ec/league/headsupplier/funds/flowlist/get", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return [$res['flow_ids'], $res['next_key'] ?? '', $res['has_more'] ?? false];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

	/**
	 * 获取资金流水详情
	 *
	 * @return array
	 */
	public function getFlowInfo(string $flow_id)
	{
		$params = [
			'flow_id' => $flow_id,
		];
		try {
			$res = $this->app->getClient()->postJson("channels/ec/league/headsupplier/funds/flowdetail/get", $params)->toArray();
			if ($res['errcode'] != 0) {
				throw new \Exception($res['errmsg']);
			}
			return $res['funds_flow'];
		} catch (\Exception $e) {
			throw new Exception($res['errmsg'] ?? $e->getMessage());
		}
	}

}
